home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / nan_news / toolkit / mouse1.prg < prev    next >
Text File  |  1991-08-17  |  23KB  |  863 lines

  1. /*
  2.  * File......: MOUSE1.PRG
  3.  * Author....: Robert DiFalco and Leo Letendre
  4.  * Date......: $Date:   17 Aug 1991 15:34:52  $
  5.  * Revision..: $Revision:   1.5  $
  6.  * Log file..: $Logfile:   E:/nanfor/src/mouse1.prv  $
  7.  * 
  8.  * This is an original work by Robert DiFalco and is placed in the
  9.  * public domain.
  10.  *
  11.  * Modification history:
  12.  * ---------------------
  13.  *
  14.  * $Log:   E:/nanfor/src/mouse1.prv  $
  15.  * 
  16.  *    Rev 1.5   17 Aug 1991 15:34:52   GLENN
  17.  * Don Caton fixed some spelling errors in the doc
  18.  * 
  19.  *    Rev 1.4   15 Aug 1991 23:06:24   GLENN
  20.  * Forest Belt proofread/edited/cleaned up doc
  21.  * 
  22.  *    Rev 1.3   17 Jul 1991 22:28:40   GLENN
  23.  * Leo fixed a potential bug in ft_mcursor().
  24.  * 
  25.  *    Rev 1.2   27 May 1991 13:40:30   GLENN
  26.  * Leo Letendre sent me a revision of MOUSE1.PRG where he built in support
  27.  * for a three-button mouse, and revised the "double click" detection 
  28.  * algorithm.
  29.  *  
  30.  * Brought in compliance with new ft_int86().
  31.  * 
  32.  *    Rev 1.1   11 May 1991 00:16:48   GLENN
  33.  * ft_mgetpos() had a bug where the x and y coordinates were reversed. 
  34.  * Changed x coordinate to aRegs[3] and y coordinate to aRegs[4], just
  35.  * like in ft_msetpos().
  36.  * 
  37.  *    Rev 1.0   01 Apr 1991 01:01:48   GLENN
  38.  * Nanforum Toolkit
  39.  *
  40.  */
  41.  
  42.  
  43. #include "FTINT86.CH"
  44.  
  45. static nMouseX, nMouseY
  46. static nHorMcks, nVerMcks
  47. static aReg[INT86_MAX_REGS]
  48. static lCrsState
  49.  
  50.  
  51. #ifdef FT_TEST
  52.  
  53.   FUNCTION MAIN()
  54.  
  55.  
  56.      local nX, nY, cSavClr
  57.      local nButCntR:=0, nButCntL:=0
  58.      local cSavScr := savescreen( 0, 0, maxrow(), maxcol() )
  59.  
  60.      if empty( FT_MRESET() )
  61.         @ maxrow(), 0 say "Mouse driver is not installed!"
  62.         return ""
  63.      endif
  64.  
  65.      * ..... Set up the screen
  66.      cSavClr := setcolor( "w/n" )
  67.      @ 0,0,maxrow(),maxcol() box "░░░░░░░░░"
  68.  
  69.      setcolor( "GR+/RB" )
  70.      scroll( 7,2,19,63,0 )
  71.      @ 7,2 to 19,63
  72.  
  73.      @ 16, 10 to 18, 40 double
  74.  
  75.      setcolor( "N/W" )
  76.      @ 17, 11 say "  Double Click here to Quit  "
  77.  
  78.      setcolor( "GR+/RB" )
  79.  
  80.      * ..... Start the demo
  81.  
  82.      FT_MSHOWCRS()
  83.  
  84.      do while .t.
  85.         nX := nY := 0
  86.  
  87.         devpos( 9, 10 )
  88.         devout( "FT_MMICKEYS:" )
  89.         FT_MMICKEYS( @nX, @nY )
  90.         devout( nX )
  91.         devout( nY )
  92.  
  93.         devpos( 10, 10 )
  94.         devout( "FT_MGETPOS :" )
  95.         DEVOUT( FT_MGETPOS( @nX, @nY ) )
  96.         devout( nX )
  97.         devout( nY )
  98.  
  99.         devpos( 11, 10 )
  100.         devout( "FT_MGETX   :" )
  101.         DEVOUT(  FT_MGETX() )
  102.  
  103.         devpos( 12, 10 )
  104.         devout( "FT_MGETY   :")
  105.         DEVOUT( FT_MGETY() )
  106.  
  107.         devpos( 13, 10 )
  108.         devout( "FT_MBUTPRS :" )
  109.         DEVOUT( FT_MBUTPRS(1,@nButCntR) )
  110.         DEVOUT( FT_MBUTPRS(0,@nButCntL) )
  111.  
  112.         DEVOUT( nButCntL )
  113.         DEVOUT( nButCntR )
  114.  
  115.         devpos( 14, 10 )
  116.         devout( "FT_MBUTREL :" )
  117.         DEVOUT( FT_MBUTREL(1) )
  118.  
  119.         if FT_MINREGION( 17, 11, 17, 39 )
  120.            if FT_MDBLCLK()
  121.               exit
  122.            endif
  123.         endif
  124.  
  125.      enddo
  126.  
  127.      FT_MHIDECRS()
  128.  
  129.      setcolor( cSavClr )
  130.      restscreen( 0, 0, maxrow(), maxcol(), cSavScr )
  131.      devpos( maxrow(), 0 )
  132.   RETURN nil
  133.  
  134.  
  135. #endif 
  136.  
  137.  
  138.  
  139.  
  140.  
  141. /*
  142.  * $DOC$         
  143.  * $FUNCNAME$
  144.  *    FT_MRESET()
  145.  * $CATEGORY$
  146.  *    Keyboard/Mouse
  147.  * $ONELINER$
  148.  *    Reset mouse driver and return status of mouse
  149.  * $SYNTAX$
  150.  *    FT_MRESET() -> nMouseStatus
  151.  * $ARGUMENTS$
  152.  *    NONE
  153.  * $RETURNS$
  154.  *    An integer representing the mouse status (0 == mouse not installed)
  155.  * $DESCRIPTION$
  156.  *    Resets the mouse driver and returns mouse status. Use FT_MSHOWCRS()
  157.  *    to display the mouse cursor.
  158.  * $EXAMPLES$
  159.  *    IF Empty( FT_MRESET() )
  160.  *       ? "No mouse driver is installed"
  161.  *    ENDIF
  162.  *  $SEEALSO$
  163.  *     FT_MSHOWCRS()
  164.  * $END$
  165.  */
  166.  
  167. FUNCTION FT_MRESET()
  168.  
  169.    aReg[1] := 0          // set mouse function call 0
  170.    FT_INT86( 51, aReg )  // execute mouse interrupt
  171.  
  172. RETURN aReg[1]            // return status code
  173.  
  174.  
  175. /* $DOC$         
  176.  * $FUNCNAME$
  177.  *    FT_MCURSOR()
  178.  * $CATEGORY$
  179.  *    Keyboard/Mouse
  180.  * $ONELINER$
  181.  *    Set the mouse cursor
  182.  * $SYNTAX$
  183.  *    FT_MCURSOR( [ <lState> ] ) -> lCursorState
  184.  * $ARGUMENTS$
  185.  *    <lState> is a logical indicating whether to set the mouse cursor on.
  186.  *             .T. - set mouse cursor on 
  187.  *             .F. - set mouse cursor off
  188.  *             If omitted, no change is made to cursor state
  189.  * $RETURNS$
  190.  *    A logical indicating the previous mouse cursor state.
  191.  * $DESCRIPTION$
  192.  *    This function works like most Clipper state functions.  If no value
  193.  *    is sent to FT_MCURSOR() it will return the state of the mouse cursor.
  194.  * $EXAMPLES$
  195.  *    IF !( FT_MCURSOR() )
  196.  *       FT_MCURSOR( .T. )
  197.  *    ENDIF
  198.  * $END$
  199.  */
  200.  
  201. FUNCTION FT_MCURSOR( lState )
  202.    local lSavState := lCrsState
  203.  
  204.    if VALTYPE(lState)="L"
  205.       if ( lCrsState := lState )
  206.          FT_MSHOWCRS()
  207.       else
  208.          FT_MHIDECRS()
  209.       endif
  210.    ENDIF
  211.  
  212. RETURN lSavState
  213.  
  214.  
  215. /* $DOC$         
  216.  * $FUNCNAME$
  217.  *    FT_MSHOWCRS()
  218.  * $CATEGORY$
  219.  *    Keyboard/Mouse
  220.  * $ONELINER$
  221.  *    Increment internal cursor flag and display mouse cursor
  222.  * $SYNTAX$
  223.  *    FT_MSHOWCRS() -> NIL
  224.  * $ARGUMENTS$
  225.  *    NONE
  226.  * $RETURNS$
  227.  *    NIL
  228.  * $DESCRIPTION$
  229.  *    Displays the mouse cursor. Make sure to turn the mouse cursor off
  230.  *    when redrawing screens.  The mouse cursor dutifully saves the screen
  231.  *    under it, so if you draw over the mouse cursor it will create a "hole"
  232.  *    in your screen when you move the mouse cursor.
  233.  * $EXAMPLES$
  234.  *    IF Empty( FT_MRESET() )
  235.  *       FT_MSHOWCRS()
  236.  *    ENDIF
  237.  *  $SEEALSO$
  238.  *     FT_MHIDECRS()
  239.  * $END$
  240.  */
  241.  
  242. FUNCTION FT_MSHOWCRS()
  243.  
  244.    aReg[1] := 1         // set mouse function call 1
  245.    FT_INT86( 51, aReg ) // execute mouse interrupt
  246.    lCrsState := .t.
  247.  
  248. RETURN NIL              // no output from function
  249.  
  250.  
  251.  
  252. /*
  253.  * $DOC$         
  254.  * $FUNCNAME$
  255.  *    FT_MHIDECRS()
  256.  * $CATEGORY$
  257.  *    Keyboard/Mouse
  258.  * $ONELINER$
  259.  *    Decrement internal mouse cursor flag and hide mouse cursor
  260.  * $SYNTAX$
  261.  *    FT_MHIDECRS() -> NIL
  262.  * $ARGUMENTS$
  263.  *    NONE
  264.  * $RETURNS$
  265.  *    NIL
  266.  * $DESCRIPTION$
  267.  *    Hides the mouse cursor. Make sure to turn the mouse cursor off when
  268.  *    redrawing screens.  The mouse cursor dutifully saves the screen
  269.  *    under it, so if you draw over the mouse cursor it will create a
  270.  *    "hole" in your screen when you move the mouse cursor.
  271.  * $EXAMPLES$
  272.  *    FT_MHIDECRS()
  273.  *    @ 10, 10 to 20, 20
  274.  *    FT_MSHOWCRS()
  275.  *  $SEEALSO$
  276.  *    FT_MSHOWCRS()
  277.  * $END$
  278.  */
  279.  
  280.  
  281.  
  282. FUNCTION FT_MHIDECRS()   // decrement internal cursor flag and hide cursor
  283.  
  284.    aReg[1] := 2          // set mouse function call 2
  285.    FT_INT86( 51, aReg )  // execute mouse interrupt
  286.    lCrsState := .f.
  287.  
  288. RETURN NIL                  // no output from function
  289.  
  290.  
  291. /*
  292.  * $DOC$         
  293.  * $FUNCNAME$
  294.  *    FT_MGETPOS()
  295.  * $CATEGORY$
  296.  *    Keyboard/Mouse
  297.  * $ONELINER$
  298.  *    Get mouse cursor position and button status
  299.  * $SYNTAX$
  300.  *    FT_MGETPOS( @<nX>, @<nY> ) -> nButtonStatus
  301.  * $ARGUMENTS$ 
  302.  *    <nX> is a variable that will receive the mouse X position.  It must
  303.  *    be passed by reference.
  304.  *
  305.  *    <nY> is a variable that will receive the mouse Y position.  It must
  306.  *    be passed by reference.
  307.  * $RETURNS$
  308.  *    an integer representing button status
  309.  *
  310.  *          - 0 for no button pressed
  311.  *          - 1 for left pressed
  312.  *          - 2 for right pressed
  313.  *          - 3 for left and right pressed
  314.  *          - 4 for middle pressed
  315.  *          - 5 for left and middle pressed
  316.  *          - 6 for right and middle pressed
  317.  *          - 0 for all three buttons pressed
  318.  * $DESCRIPTION$
  319.  *    Loads cursor position into x and y coordinates passed by reference and
  320.  *    returns the button status.
  321.  * $EXAMPLES$
  322.  *    LOCAL nX, nY
  323.  *    LOCAL nButton := FT_MGETPOS( @nX, @nY )
  324.  *    ? "Mouse Row    :", nX
  325.  *    ? "Mouse Column :", nY
  326.  *    ? "Button Status:", nButton
  327.  *  $SEEALSO$
  328.  *    FT_MSETPOS() FT_MDEFCRS() FT_MGETX() FT_MGETY()
  329.  * $END$
  330.  */
  331.  
  332.  
  333.  
  334.  
  335. FUNCTION FT_MGETPOS( nX, nY )
  336.  
  337.    nX := if( nX == NIL, 0, nX )
  338.    nY := if( nY == NIL, 0, nX )
  339.  
  340.    aReg[1] := 3                // set mouse function call 3
  341.    FT_INT86( 51, aReg )        // execute mouse interrupt
  342.    nX := nMouseX := aReg[4]    // store new x-coordinate
  343.    nY := nMouseY := aReg[3]    // store new y-coordinate
  344.  
  345. RETURN aReg[2]                 // return button status
  346.  
  347. /* $DOC$         
  348.  * $FUNCNAME$
  349.  *    FT_MGETX()
  350.  * $CATEGORY$
  351.  *    Keyboard/Mouse
  352.  * $ONELINER$
  353.  *    Get mouse cursor row position
  354.  * $SYNTAX$
  355.  *    FT_MGETX() -> nRowPos
  356.  * $ARGUMENTS$
  357.  *    NONE
  358.  * $RETURNS$
  359.  *    Row position of mouse
  360.  * $DESCRIPTION$
  361.  *    Retrieves mouse's row position
  362.  * $EXAMPLES$ 
  363.  *    ? FT_MGETX()
  364.  *  $SEEALSO$
  365.  *     FT_MDEFCRS() FT_MGETPOS() FT_MGETY()
  366.  * $END$
  367.  */
  368.  
  369. FUNCTION FT_MGETX()
  370.    FT_MGETPOS()
  371. RETURN int( nMouseX / 8 )
  372.  
  373. /*
  374.  * $DOC$         
  375.  * $FUNCNAME$
  376.  *    FT_MGETY()
  377.  * $CATEGORY$
  378.  *    Keyboard/Mouse
  379.  * $ONELINER$
  380.  *    Get mouse cursor column position
  381.  * $SYNTAX$
  382.  *    FT_MGETY() -> nColPos
  383.  * $ARGUMENTS$
  384.  *    NONE
  385.  * $RETURNS$
  386.  *    Column position of mouse.
  387.  * $DESCRIPTION$
  388.  *    Retrieves mouse's column position.
  389.  * $EXAMPLES$
  390.  *    ? FT_MGETY()
  391.  *  $SEEALSO$
  392.  *    FT_MDEFCRS() FT_MGETPOS() FT_MGETX()
  393.  * $END$
  394.  */
  395.  
  396. FUNCTION FT_MGETY()
  397.    FT_MGETPOS()
  398. RETURN int( nMouseY / 8 )
  399.  
  400. /*
  401.  * $DOC$         
  402.  * $FUNCNAME$
  403.  *    FT_MSETPOS()
  404.  * $CATEGORY$
  405.  *    Keyboard/Mouse
  406.  * $ONELINER$
  407.  *    Position the mouse cursor
  408.  * $SYNTAX$
  409.  *    FT_MSETPOS( <nX>, <nY> ) -> NIL
  410.  * $ARGUMENTS$ 
  411.  *    <nX> is the desired mouse row.
  412.  *
  413.  *    <nY> is the desired mouse column.
  414.  * $RETURNS$
  415.  *    NIL
  416.  * $DESCRIPTION$
  417.  *    Positions mouse cursor on screen.
  418.  * $EXAMPLES$
  419.  *    FT_MSETPOS( 10, 20 )     // position mouse cursor at row 10, col 20
  420.  *  $SEEALSO$
  421.  *    FT_MGETPOS() FT_MDEFCRS() FT_MGETX() FT_MGETY()
  422.  * $END$
  423.  */
  424.  
  425. FUNCTION FT_MSETPOS( nX, nY )  // set mouse cursor location
  426.  
  427.    aReg[1] := 4                // set mouse function call 4
  428.    aReg[3] := nY               // assign new x-coordinate
  429.    aReg[4] := nX               // assign new y-coordinate
  430.    FT_INT86( 51, aReg )        // execute mouse interrupt
  431.  
  432. RETURN NIL                     // no function output
  433.  
  434. /*
  435.  * $DOC$         
  436.  * $FUNCNAME$
  437.  *    FT_MXLIMIT()
  438.  * $CATEGORY$
  439.  *    Keyboard/Mouse
  440.  * $ONELINER$
  441.  *    Set vertical bounds of mouse travel
  442.  * $SYNTAX$
  443.  *    FT_MXLIMIT( <nX1>, <nX2> ) -> NIL
  444.  * $ARGUMENTS$
  445.  *    <nX1> is the top row limit.
  446.  *
  447.  *    <nX2> is the bottom row limit.
  448.  * $RETURNS$
  449.  *    NIL
  450.  * $DESCRIPTION$
  451.  *    Set maximum vertical bounds of mouse.
  452.  * $EXAMPLES$
  453.  *    FT_MXLIMIT( 10, 20 )
  454.  *  $SEEALSO$
  455.  *     FT_MYLIMIT() FT_MINREGION()
  456.  * $END$
  457.  */
  458.  
  459. FUNCTION FT_MXLIMIT( nXMin, nXMax )   // set vertical minimum and maximum coordinates
  460.  
  461.    aReg[1] = 7                        // set mouse function call 7
  462.    aReg[3] = nXMin                    // load vertical minimum parameter
  463.    aReg[4] = nXMax                    // load vertical maximum parameter
  464.    FT_INT86( 51, aReg )               // execute mouse interrupt
  465.  
  466. RETURN NIL
  467.  
  468. /*
  469.  * $DOC$         
  470.  * $FUNCNAME$
  471.  *    FT_MYLIMIT()
  472.  * $CATEGORY$
  473.  *    Keyboard/Mouse
  474.  * $ONELINER$
  475.  *    Set horizontal bounds of mouse travel
  476.  * $SYNTAX$
  477.  *    FT_MYLIMIT( <nY1>, <nY2> ) -> NIL
  478.  * $ARGUMENTS$
  479.  *    <nY1> is the left column limit.
  480.  *
  481.  *    <nY2> is the right column limit.
  482.  * $RETURNS$
  483.  *    NIL
  484.  * $DESCRIPTION$
  485.  *    Set maximum horizontal bounds of mouse.
  486.  * $EXAMPLES$
  487.  *    FT_MYLIMIT( 10, 20 )
  488.  *  $SEEALSO$
  489.  *     FT_MXLIMIT() FT_MINREGION()
  490.  * $END$
  491.  */
  492.  
  493. FUNCTION FT_MYLIMIT( nYMin, nYMax )  // set horizontal minimum and maximum coordinates
  494.  
  495.    aReg[1] = 8                       // set mouse function call 8
  496.    aReg[3] = nYMin                   // load horz minimum parameter
  497.    aReg[4] = nYMax                   // load horz maximum parameter
  498.    FT_INT86( 51, aReg )              // execute mouse interrupt
  499.  
  500. RETURN NIL                           // no function output
  501.  
  502.  
  503. /*
  504.  * $DOC$         
  505.  * $FUNCNAME$
  506.  *    FT_MBUTPRS()
  507.  * $CATEGORY$
  508.  *    Keyboard/Mouse
  509.  * $ONELINER$
  510.  *    Retrieve button press status
  511.  * $SYNTAX$
  512.  *    FT_MRESET( <nButton> [, @nButPrs [, @nX [, @nY] ] ] ) -> nButStatus
  513.  * $ARGUMENTS$
  514.  *    <nButton> is the mouse button number:
  515.  *
  516.  *               0 - Left   Button
  517.  *               1 - Right  Button
  518.  *               2 - Middle Button [if applicable]
  519.  *
  520.  *    <nButPrs> is the number of times the specified button was pressed
  521.  *              since the last call to this routine. PASSED BY REFERENCE.
  522.  *    <nX> is the X position of the cursor when the last press occurred. PASSED
  523.  *              BY REFERENCE.
  524.  *    <nY> is the Y position of the cursor when the last press occurred. PASSED
  525.  *              BY REFERENCE.
  526.  *
  527.  * $RETURNS$
  528.  *    An integer representing the button status:
  529.  *
  530.  *               0 - no buttons pressed
  531.  *               1 - left button pressed
  532.  *               2 - right button pressed
  533.  *               3 - left and right pressed
  534.  *               4 - middle pressed
  535.  *               5 - left and middle pressed
  536.  *               6 - middle and right buttons pressed
  537.  *               7 - all 3 buttons pressed
  538.  * $DESCRIPTION$
  539.  *    Retrieves the mouse button status.
  540.  * $EXAMPLES$
  541.  *    IF Empty( FT_MBUTPRS(1) )
  542.  *       ? "No Item selected"
  543.  *    ENDIF
  544.  *  $SEEALSO$
  545.  *     FT_MBUTREL() FT_MDBLCLK()
  546.  * $END$
  547.  */
  548.  
  549. FUNCTION FT_MBUTPRS( nButton, nButPrs, nX, nY ) // get button press information
  550.  
  551.    aReg[1] := 5               // set mouse function call 5
  552.    aReg[2] := nButton          // pass parameter for left or right button
  553.    FT_INT86( 51, aReg )        // execute mouse interrupt
  554.    nButPrs := aReg[2] // store updated press count
  555.    nX := aReg[4]      // x-coordinate at last press
  556.    nY := aReg[3]      // y-coordinate at last press
  557.  
  558. RETURN aReg[1]                 // return button status
  559.  
  560.  
  561.  
  562. /*  $DOC$
  563.  *  $FUNCNAME$
  564.  *     FT_MBUTREL()
  565.  *  $CATEGORY$
  566.  *     Keyboard/Mouse
  567.  *  $ONELINER$
  568.  *     Get mouse button release information
  569.  *  $SYNTAX$
  570.  *     FT_MBUTREL( nButton [, @nButRel [, @nX [, @nY] ] ]) -> nBStat
  571.  *  $ARGUMENTS$
  572.  *     <nButton> is the mouse button number
  573.  *               0 - Left   Button
  574.  *               1 - Right  Button
  575.  *               2 - Middle Button [if applicable]
  576.  *
  577.  *    <nButRel> is the number of times the specified button was released
  578.  *              since the last call to this routine. PASSED BY REFERENCE.
  579.  *
  580.  *    <nX> is the X position of the cursor when the last release occurred.
  581.  *              PASSED BY REFERENCE.
  582.  *
  583.  *    <nY> is the Y position of the cursor when the last release occurred.
  584.  *              PASSED BY REFERENCE.
  585.  *  $RETURNS$
  586.  *     <nBStat>  - an integer representing button release status
  587.  *                 0 - None
  588.  *                 1 - Left
  589.  *                 2 - Right
  590.  *                 3 - Middle
  591.  *  $DESCRIPTION$
  592.  *     This function returns the release status of the mouse buttons.
  593.  *  $EXAMPLES$
  594.  *     IF( FT_MBUTREL( 0 ) == 1 )
  595.  *        ? "Left button released"
  596.  *     ENDIF
  597.  *  $SEEALSO$
  598.  *     FT_MBUTPRS() FT_MDBLCLK()
  599.  *  $END$
  600.  */
  601.  
  602.  
  603.  
  604. FUNCTION FT_MBUTREL( nButton, nButRel, nX, nY ) // get button release information
  605.  
  606.    aReg[1] := 6                // set mouse function call 6
  607.    aReg[2] := nButton          // pass parameter for left or right button
  608.    FT_INT86( 51, aReg )        // execute mouse interrupt
  609.    nButRel := aReg[2]  // store updated release count 
  610.    nX := aReg[4]      // x-coordinate at last release
  611.    nY := aReg[3]      // y-coordinate at last release
  612.  
  613. RETURN aReg[1]                 // return button status
  614.  
  615.  
  616. /*
  617.  * $DOC$         
  618.  * $FUNCNAME$
  619.  *    FT_MDEFCRS()
  620.  * $CATEGORY$
  621.  *    Keyboard/Mouse
  622.  * $ONELINER$
  623.  *    Define the mouse cursor
  624.  * $SYNTAX$
  625.  *    FT_MDEFCRS( <nCrsType>, <nScrMask>, <nCrsMask> ) -> NIL
  626.  * $ARGUMENTS$
  627.  *    <nCrsType> is the cursor type.
  628.  *
  629.  *    <nScrMask> is the screen mask.
  630.  *
  631.  *    <nCrsMask> is the cursor mask.
  632.  * $RETURNS$
  633.  *    NIL
  634.  * $DESCRIPTION$
  635.  *    Defines the cursor type
  636.  * $END$
  637.  */
  638.  
  639. FUNCTION FT_MDEFCRS( nCurType, nScrMask, nCurMask )   // define text cursor type and masks
  640.  
  641.    aReg[1] = 10          // set mouse function call 10
  642.    aReg[2] = nCurType   // load cursor type parameter
  643.    aReg[3] = nScrMask   // load screen mask value
  644.    aReg[4] = nCurMask   // load cursor mask value
  645.    FT_INT86( 51, aReg ) // execute mouse interrupt
  646.  
  647. RETURN NIL              // no function output
  648.  
  649.  
  650. /*
  651.  * $DOC$         
  652.  * $FUNCNAME$
  653.  *    FT_MMICKEYS()
  654.  * $CATEGORY$
  655.  *    Keyboard/Mouse
  656.  * $ONELINER$
  657.  *    Get mickeys
  658.  * $SYNTAX$
  659.  *    FT_MMICKEYS( @<nX>, @<nY> ) -> NIL
  660.  * $ARGUMENTS$
  661.  *    <nX> is a variable that will receive the vertical mickey count.
  662.  *
  663.  *    <nY> is a variable that will receive the horizontal mickey count.
  664.  * $RETURNS$
  665.  *    NIL
  666.  * $DESCRIPTION$
  667.  *    <nX> and <nY> must be passed by reference to receive
  668.  *    the mouse position in Mickeys.
  669.  * $EXAMPLES$
  670.  *    FT_MMICKEYS( @nX, @nY )
  671.  *    ? nX
  672.  *    ? nY
  673.  * $END$
  674.  */
  675.  
  676. FUNCTION FT_MMICKEYS( nX, nY ) // read mouse motion counters
  677.  
  678.    aReg[1] = 11                // set mouse function call 11
  679.    FT_INT86( 51, aReg )        // execute mouse interrupt
  680.    nX := nHorMcks := aReg[3]   // store horizontal motion units
  681.    nY := nVerMcks := aReg[4]   // store vertical motion units
  682.  
  683. RETURN NIL                     // no function output
  684.  
  685.  
  686. /*
  687.  * $DOC$         
  688.  * $FUNCNAME$
  689.  *    FT_MDBLCLK()
  690.  * $CATEGORY$
  691.  *    Keyboard/Mouse
  692.  * $ONELINER$
  693.  *    Return true if a double click was detected
  694.  * $SYNTAX$
  695.  *    FT_MDBFCLK( [ <nClick> [, <nButton> [, <nInterval> [, <nRow> [, <nCol>;
  696.  *                [, <nTime> ] ] ] ] ] ] ) -> lIsDoubleClk
  697.  * $ARGUMENTS$
  698.  *    <nClick> is a numeric value.  If it is zero FT_MDBLCLK() will not 
  699.  *             check for the first press but rather will simply wait the
  700.  *             specified period for a single press. This is useful if this
  701.  *             routine is called from one which in turn responded to a button
  702.  *             press. If it is not present or not equal to 0, then FT_MDBLCLK()
  703.  *             will wait for two presses of the specified button.
  704.  *
  705.  *    <nButton> is the mouse button number
  706.  *               0 - Left   Button
  707.  *               1 - Right  Button
  708.  *               2 - Middle Button [if applicable]
  709.  *
  710.  *    <nInterval> is the interval to wait for the first click if requested
  711.  *           and the time to wait for the second. If not present then defaults
  712.  *           to 0.5 second.
  713.  *
  714.  *    <nRow> is the row number for the mouse cursor location for a double click
  715.  *           to be valid. If not present then the current position is taken as
  716.  *           the valid location.
  717.  *
  718.  *    <nCol> is the column number for the mouse cursor location for a double
  719.  *           click to be valid. If not present, then the current position is
  720.  *           taken as the valid location.
  721.  *
  722.  *    <nTime> is an optional start time for the waiting period for the first
  723.  *           click (of either one or two requested). If not given then the
  724.  *           time is set at entry into this routine. This is useful when this
  725.  *           routine is called from another routine which was called in 
  726.  *           response to a mouse click but needs to know if a double click
  727.  *           has occurred
  728.  * $RETURNS$
  729.  *    .T. if a double click was detected.
  730.  * $DESCRIPTION$
  731.  *    This is a mouse meta function that checks for the presence
  732.  *    of a double click.
  733.  * $EXAMPLES$
  734.  *   IF FT_MISREGION( 10, 10, 11, 20 ) .AND.;
  735.  *      FT_MDBLCLK(0,1,,FT_MGETX(),FT_MGETY())  && double click, right button
  736.  *                                              && at current location with
  737.  *                                              && default interval
  738.  *
  739.  *         MnuItem1()
  740.  *   ENDIF
  741.  *  $SEEALSO$
  742.  *     FT_MBUTPRS() FT_MBUTREL()
  743.  * $END$
  744.  */
  745.  
  746. FUNCTION FT_MDBLCLK( nClick, nButton, nInterval, nRow, nCol, nStart )
  747.  
  748. LOCAL nVert, nHorz  // local row and col coordinates
  749. LOCAL lDouble:=.F.  // double click actually occurred
  750. LOCAL lDone          // loop flag
  751. LOCAL nPrs           // number of presses which occurred
  752.  
  753. * Initialize any empty arguments
  754.  
  755.    if nClick=NIL
  756.       nClick=1
  757.    endif
  758.  
  759.    if nButton=NIL
  760.         nButton=0
  761.    endif
  762.  
  763.    if nRow=NIL
  764.        nRow=FT_MGETX()
  765.    endif
  766.  
  767.    if nCol=NIL
  768.        nCol=FT_MGETY()
  769.    endif
  770.  
  771.    if nInterval=NIL
  772.        nInterval=0.5
  773.    endif
  774.  
  775.    if nStart=NIL
  776.        nStart=seconds()
  777.    endif
  778.  
  779.    nVert=nRow
  780.    nHorz=nCol
  781.    lDouble:=lDone:=nClick==0
  782.    
  783.    // Wait for first press if requested
  784.  
  785.    do while !lDone
  786.  
  787.            FT_MBUTPRS( nButton, @nPrs, @nVert, @nHorz )
  788.            nVert=INT(nVert/8)
  789.            nHorz=INT(nHorz/8)
  790.  
  791.            lDouble=(nPrs>0)
  792.            ldone= seconds() - nStart >= nInterval .or. lDouble
  793.            
  794.    enddo
  795.  
  796.    // if we have not moved then keep the preliminary double click setting
  797.  
  798.    lDouble=lDouble.and.(nVert=nRow.and.nHorz=nCol)
  799.  
  800.    // change start time if we waited for first click. nInterval is the
  801.    // maximum time between clicks not the total time for two clicks if 
  802.    // requested.
  803.  
  804.    if nClick>0
  805.       nStart=seconds()
  806.    endif
  807.  
  808.    // If we have fulfilled all of the requirements then wait for second click
  809.  
  810.    if lDouble
  811.  
  812.       lDouble:=lDone:=.F.
  813.       
  814.       do while !lDone
  815.  
  816.            FT_MBUTPRS( nButton, @nPrs, @nVert, @nHorz )
  817.            nVert=INT(nVert/8)
  818.            nHorz=INT(nHorz/8)
  819.  
  820.            lDouble=(nPrs>0)
  821.            lDone= seconds() - nStart >= nInterval .or. lDouble
  822.            
  823.       enddo
  824.  
  825.   // make sure we haven't moved 
  826.  
  827.       lDouble=lDouble.and.(nVert=nRow.and.nHorz=nCol)
  828.  
  829.    endif
  830.  
  831.  
  832. RETURN lDouble
  833.  
  834. /*
  835.  * $DOC$         
  836.  * $FUNCNAME$
  837.  *    FT_MINREGION()
  838.  * $CATEGORY$
  839.  *    Keyboard/Mouse
  840.  * $ONELINER$
  841.  *    Test if the mouse cursor is in the passed region
  842.  * $SYNTAX$
  843.  *    FT_MINREGION( <nT>, <nL>, <nB>, <nR> ) -> lInRegion
  844.  * $ARGUMENTS$
  845.  *    <nT>, <nL> <nB> <nR> are the four corners of the screen region.
  846.  * $RETURNS$
  847.  *    .T. if mouse is in specified region.
  848.  * $DESCRIPTION$
  849.  *    This function will check to see if the mouse cursor is
  850.  *    within the confines of the specified region.
  851.  * $EXAMPLES$
  852.  *    IF FT_MINREGION( 10, 10, 11, 20 )
  853.  *      nChoice := 1
  854.  *    ENDIF
  855.  *  $SEEALSO$
  856.  *     FT_MXLIMIT() FT_MYLIMIT() FT_MINREGION()
  857.  * $END$
  858.  */
  859.  
  860. FUNCTION FT_MINREGION( nTR, nLC, nBR, nRC )
  861. RETURN ( FT_MGETX() >= nTR .and. FT_MGETX() <= nBR .and. ;
  862.          FT_MGETY() >= nLC .and. FT_MGETY() <= nRC )
  863.